package com.iflytek.cosmo.ocr.common.core.worker;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.iflytek.cosmo.ocr.common.constant.CommonConstant;
import com.iflytek.cosmo.ocr.common.core.BeanHelper;
import com.iflytek.cosmo.ocr.common.core.station.AbstractStation;
import com.iflytek.cosmo.ocr.common.core.task.RecognizedTask;
import com.iflytek.cosmo.ocr.common.json.Jackson;
import com.iflytek.cosmo.ocr.common.util.FileUtil;
import com.iflytek.cosmo.ocr.common.util.HtmlWordUtil;
import com.iflytek.cosmo.ocr.common.util.ImageUtil;
import com.iflytek.cosmo.ocr.common.util.JSONUtil;
import com.iflytek.cosmo.ocr.common.util.UUIDUtil;
import com.iflytek.cosmo.ocr.dao.OcrResultDao;
import com.iflytek.cosmo.ocr.model.domain.FileInfo;
import com.iflytek.cosmo.ocr.model.domain.OcrResultOutput;
import com.iflytek.cosmo.ocr.model.entity.OcrResultEntity;
import com.iflytek.cosmo.ocr.service.FileService;
import com.iflytek.cosmo.ocr.service.RecogniseService;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpHeaders;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import tk.mybatis.mapper.entity.Example;

/**
 *识别工人
 */
public class RecognizedWorker implements Runnable{

    /**
     * 日志记录器
     */
    private Logger logger = LoggerFactory.getLogger(RecognizedWorker.class);

    private RecognizedTask task;
    /**
     * 下一个工作台
     */
    private AbstractStation nextStation;

    public RecognizedWorker(RecognizedTask task, AbstractStation nextStation) {
        this.task = task;
        this.nextStation = nextStation;
    }

    @Override
    public void run() {
        logger.debug("开始图片识别任务, fileName: {}", task.getFileInfo().getFileName());
        //取参数
        FileInfo fileInfo = task.getFileInfo();
        String fileName = fileInfo.getFileName();
        String fileType = fileInfo.getFileType();
        String fileId = fileInfo.getId();
        Long fileSize = fileInfo.getFileSize();

        FileService fileService= BeanHelper.getFileServiceBean();

        //下载要识别的文件，图片
        byte[] bytes = fileService.getFileBytes(task.getFileInfo().getFilePath());

        // pdf子页面压缩
        if (StringUtils.isNotEmpty(fileInfo.getParentId())) {
            // 转换后的图片处理
            if (fileSize > CommonConstant.FORMAT_MIN_SIZE) {
                // 压缩图片文件
                logger.debug("------- 开始pdf子图片压缩-------");

                double rate = (double) CommonConstant.FORMAT_MIN_SIZE / (double) fileSize;
                try (InputStream is = new ByteArrayInputStream(bytes);
                    ByteArrayOutputStream reduceStream = (ByteArrayOutputStream) ImageUtil.reduceImgByRate(is, rate)) {
                    if (reduceStream != null) {
                        byte[] reduceBytes = reduceStream.toByteArray();
                        long formatSize = reduceBytes.length;
                        String formatPath = fileService.uploadFile(fileName, "jpg", reduceBytes);
                        reduceStream.close();

                        // 更新格式化信息
                        fileInfo.setFormatType("jpg");
                        fileInfo.setFormatSize(formatSize);
                        fileInfo.setFormatPath(formatPath);

                        fileService.saveFileInfo(fileInfo);
                    }
                }
                catch (Exception e) {
                    logger.debug("开始pdf子图片压缩异常, fileId: {}", fileId, e);
                }
            }
        }

        try {
            TimeUnit.SECONDS.sleep(RandomUtils.nextInt(1, 3));
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 进行识别服务
        OcrResultOutput ocrResultOutput = processRecognise(fileName, fileType, bytes);

        // 转换存储对象
        logger.debug("------- 保存子文件识别结果 -------");
        OcrResultEntity ocrResultEntity = new OcrResultEntity();
        ocrResultEntity.setFileId(fileId);
        ocrResultEntity.setGroupId(fileInfo.getParentId());
        ocrResultEntity.setStatus(ocrResultOutput.getStatus());
        ocrResultEntity.setResult(ocrResultOutput.getResult());
        ocrResultEntity.setText(ocrResultOutput.getText());
        ocrResultEntity.setHtml(ocrResultOutput.getHtml());
        ocrResultEntity.setIsDelete(0);
        addOrUpdateOcrResult(ocrResultEntity);
        
        logger.debug("------- 保存子文件识别结果的HTML -------");
        JSONObject bodyJson = JSON.parseObject(ocrResultOutput.getResult());
        if(null!=bodyJson) {
        	JSONArray tableArray = bodyJson.getJSONArray("Table"); 
            if( null!=tableArray&& !tableArray.isEmpty() && tableArray.size() >0) {
            	RecogniseService recogniseService =BeanHelper.getRecogniseService();
                recogniseService.viewTableHtml(fileId);
            }
        }
        bytes = null;

        return;
    }

    /**
     *
     * @param ocrResultEntity
     */
    public void addOrUpdateOcrResult(OcrResultEntity ocrResultEntity) {

        OcrResultDao ocrResultDao= BeanHelper.getOcrResultDao();

        if (ocrResultEntity != null) {
            // 查询条件
            Example example = new Example(OcrResultEntity.class);
            Example.Criteria criteria = example.createCriteria();
            // id条件
            String id = ocrResultEntity.getId();
            if (StringUtils.isNotBlank(id)) {
                criteria.andEqualTo("id", id);
            }
            // fileId条件
            String fileId = ocrResultEntity.getFileId();
            if (StringUtils.isNotBlank(fileId)) {
                criteria.andEqualTo("fileId", fileId);
            }
            List<OcrResultEntity> ocrResultList = ocrResultDao.selectByExample(example);

            Date current = new Date();
            if (ocrResultList != null && ocrResultList.size() > 0) {
                // 更新
                ocrResultEntity.setUpdateTime(current);
                ocrResultDao.updateByExampleSelective(ocrResultEntity, example);
            } else {
                // 新增
                ocrResultEntity.setId(UUIDUtil.getUUID());
                if (StringUtils.isEmpty(ocrResultEntity.getGroupId())) {
                    ocrResultEntity.setGroupId(ocrResultEntity.getFileId());
                }
                ocrResultEntity.setCreateTime(current);
                ocrResultEntity.setUpdateTime(current);

                ocrResultDao.insert(ocrResultEntity);
            }
        }
    }

    /**
     * 进行识别服务
     *
     * @param fileName 文件名
     * @param fileType 文件类型
     * @param bytes    文件数据
     * @return 识别结果
     * @throws Exception Exception
     */
    private OcrResultOutput processRecognise(String fileName, String fileType, byte[] bytes) {
        long startTime = System.currentTimeMillis();
        // ocr结果对象
        OcrResultOutput ocrResultOutput = new OcrResultOutput();
        //fileName = new String(fileName.getBytes(Charset.forName("utf-8")),Charset.forName("iso-8859-1")); //中文乱码问题
        // 判断后缀名
        if ("jpg".equalsIgnoreCase(fileType) || "jpeg".equalsIgnoreCase(fileType) || "png".equalsIgnoreCase(fileType) || "bmp".equalsIgnoreCase(fileType)
                || "tif".equalsIgnoreCase(fileType) || "tiff".equalsIgnoreCase((fileType))) {
            // 调用ocr引擎
            try {
                long startTime1 = System.currentTimeMillis();
                String result = formOcrService(fileName, bytes);
                long endTime1 = System.currentTimeMillis();
                logger.info("图文识别方法所需要时间：" + (endTime1 - startTime1));
                ocrResultOutput.setStatus(CommonConstant.RECG_SUCCESS);
                ocrResultOutput.setResult(extractResultBody(result));
                ocrResultOutput.setText(extractResultText(result));
            } catch (Exception e) {
                logger.error("进行识别服务-调用ocr引擎出错");
                ocrResultOutput.setStatus(CommonConstant.RECG_FAIL_ENGINE);
            }
        } else if ("doc".equalsIgnoreCase(fileType) || "docx".equalsIgnoreCase(fileType)) {
            // word转换成html
            try {
                String html = HtmlWordUtil.wordToHtml(bytes, fileType);
                ocrResultOutput.setStatus(CommonConstant.RECG_SUCCESS);
                ocrResultOutput.setHtml(html);
            } catch (Exception e) {
                logger.error("进行识别服务-word解析出错");
                ocrResultOutput.setStatus(CommonConstant.RECG_FAIL_FORMAT);
            }
        } else if ("txt".equals(fileType)) {
            // text读取文字
            try {
                String text = FileUtil.byteToStr(bytes);
                ocrResultOutput.setStatus(CommonConstant.RECG_SUCCESS);
                ocrResultOutput.setText(text);
            } catch (Exception e) {
                logger.error("进行识别服务-text解析出错");
                ocrResultOutput.setStatus(CommonConstant.RECG_FAIL_FORMAT);
            }
        }
        bytes = null;
        //logger.info("识别结束，任务减1，当前task任务数量：" + taskNums.decrementAndGet());
        long endTime = System.currentTimeMillis();
        logger.info("图文识别前后共需要时间：" + (endTime - startTime));
        return ocrResultOutput;
    }

    /**
     * 提取识别结果的纯文本内容
     */
    private String extractResultText(String restResult) {
        String msgText = StringUtils.EMPTY;
        if (StringUtils.isBlank(restResult)) {
            return msgText;
        }

        try {
            msgText = JSONUtil.getProp(JSONUtil.toJsonNode(restResult), "msgText", String.class);
        } catch (IOException e) {
            logger.warn("解析 ocr 识别结果异常. ocrResult: {}", restResult, e);
        }

        return msgText;
    }

    /**
     * 提取识别结果的原始
     */
    private String extractResultBody(String restResult) {
        String result = StringUtils.EMPTY;
        // 判断rest返回结果是否有值
        if (StringUtils.isNotBlank(restResult)) {
            JsonNode restResultNode = Jackson.parseJsonNode(restResult);

            int msgStatus = restResultNode.get("msgStatus").intValue();
            if (msgStatus == 0) {
                result = restResultNode.get("msgBody").textValue();
            }
        }
        return result;
    }

    /**
     * 调用ocr服务生成结果
     *
     * @param fileName 文件名
     * @param bytes    文件内容
     * @return 识别结果
     */
    private String formOcrService(String fileName, byte[] bytes) throws Exception {

        String cosmoUrl=BeanHelper.getRecognizeConfig().getCosmoUrl();
        RestTemplate restTemplate=BeanHelper.getRestTemplate();
        // 请求路径
        String requestUrl = cosmoUrl + "/iflytek/ocr/view/fileExtra";

        HttpHeaders requestHeaders = new HttpHeaders();
        requestHeaders.set("Accept", "text/plain");
        requestHeaders.set("Content-Type", "multipart/form-data");

        ByteArrayResource resource = new ByteArrayResource(bytes) {
            @Override
            public String getFilename() {
                return fileName;
            }
        };

        MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
        param.add("picFile", resource);
        param.add("name", fileName);

        // 发起请求
        logger.debug("开始调用ocr服务, url: {}", requestUrl);

        String restResult = StringUtils.EMPTY;
        try {
            long startTime1 = System.currentTimeMillis();
            restResult = restTemplate.postForObject(requestUrl, param, String.class);
            long endTime1 = System.currentTimeMillis();
            logger.info("方法所需要时间：" + (endTime1 - startTime1));
            resource = null;
        } catch (Exception e) {
            logger.error("调用ocr服务时出错，错误信息：" + e);
            throw e;
        }

        bytes = null;
        return restResult;
    }
}
